<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <button>点我</button>
</body>
<script>
    {
        // **默认绑定** ：常用的函数调用类型：独立函数调用
        // * 可以把这个规则看作是无法应用其他规则的时候默认的规则，基本指向的是window
        // function fn(){
        //     "use strict";
        //     console.log(this);// window,严格模式下为undefined
        // }
        // fn();

    }
    {
        // 隐式绑定 ：如果函数调用时，前面存在调用它的对象，那么this就会隐式绑定到这个对象上
        // * 当函数引用有上下文对象的时候（obj），隐式绑定规则会把函数中的this绑定到这个上下文对象上
        // const obj = {
        //     fn(){
        //         "use strict";
        //         console.log("fn",this);
        //     }
        // }
        // obj.fn();


        // * 隐式绑定可能会出现隐式丢失的问题 ：被隐式绑定的函数，会丢失了绑定对象
        // const obj = {
        //     fn(){
        //         "use strict";
        //         console.log("fn",this);
        //     }
        // }
        // const fn2 = obj.fn;
        // fn2();
    }
    {
        // **显式绑定**： 指我们通过call、apply以及bind方法改变this的行为，相比隐式绑定，我们能清楚的感知 this 指向变化过程
        window.userName = "window->userName";
        const obj = {
            userName:"obj->userName",
            fn(){
                console.log(this.userName);
            }
        };
        const obj2 = {
            userName:"obj2->userName"
        }
        // 隐式绑定
        // obj.fn();// obj
        // const fn2 = obj.fn;
        // fn2();// window

        // 显式绑定-call
        // obj.fn.call(window);// window
        // obj.fn.call(obj2);// obj2

        // 显式绑定-apply
        // obj.fn.apply(window);// window
        // obj.fn.apply(obj2);// obj2

        // 显式绑定-bind
        // const fn2 = obj.fn.bind(window);
        // fn2();// window
        // obj.fn.bind(obj2)();// obj2


    }
    {
        // **`new`绑定**：构造函数只是一些使用new操作符被调用的函数,使用new调用函数的时候，会构造一新的对象，
        // 这个时候 就把新的对象绑定给了函数的this上
        // new对象的过程：
        // 1- 调用Box函数
        // 2- 隐式创建一个对象，并将this指向到该对象。
        // 3- 执行函数
        // 4- 隐式返回this
        // function Box(a,b){
        //     this.a = a;
        //     this.b = b;
        //     this.fn = function(){
        //         console.log(this);
        //     }
        //     this.run();
        // }
        // Box.prototype.run = function(){
        //     console.log(this);
        // }
        // const obj = new Box(1,2);
        // obj.fn();
        // obj.run();
    }

    const btn = document.querySelector("button");
    btn.onclick = function(){
        console.log(this);
    }
</script>
</html>